package com.laiketui.admin.store.service.dubbo.order;

import com.gexin.fastjson.JSON;
import com.gexin.fastjson.TypeReference;
import com.google.common.collect.Maps;
import com.laiketui.admin.store.api.order.IndexService;
import com.laiketui.common.api.*;
import com.laiketui.common.mapper.*;
import com.laiketui.common.utils.algorithm.DataAlgorithmTool;
import com.laiketui.common.utils.tool.DateUtil;
import com.laiketui.common.utils.tool.cache.RedisDataTool;
import com.laiketui.common.utils.tool.data.GoodsDataUtils;
import com.laiketui.common.utils.tool.file.EasyPoiExcelUtil;
import com.laiketui.core.cache.RedisUtil;
import com.laiketui.core.common.SplitUtils;
import com.laiketui.core.exception.LaiKeAPIException;
import com.laiketui.core.lktconst.GloabConst;
import com.laiketui.core.utils.tool.DataUtils;
import com.laiketui.domain.config.*;
import com.laiketui.domain.file.FileDeliveryModel;
import com.laiketui.domain.lktconst.DictionaryConst;
import com.laiketui.domain.lktconst.ErrorCode;
import com.laiketui.domain.log.AdminRecordModel;
import com.laiketui.domain.log.SignRecordModel;
import com.laiketui.domain.mch.AdminModel;
import com.laiketui.domain.mch.MchBrowseModel;
import com.laiketui.domain.mch.MchConfigModel;
import com.laiketui.domain.order.ExpressDeliveryModel;
import com.laiketui.domain.order.OrderConfigModal;
import com.laiketui.domain.order.OrderDetailsModel;
import com.laiketui.domain.order.OrderModel;
import com.laiketui.domain.product.StockModel;
import com.laiketui.domain.user.User;
import com.laiketui.domain.user.UserAddress;
import com.laiketui.domain.vo.MainVo;
import com.laiketui.domain.vo.Tool.ExcelAnalysisVo;
import com.laiketui.domain.vo.Tool.ExcelParamVo;
import com.laiketui.domain.vo.goods.AddStockVo;
import com.laiketui.domain.vo.order.*;
import com.laiketui.root.common.BuilderIDTool;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.*;

import static com.laiketui.domain.lktconst.DictionaryConst.OrdersStatus.ORDERS_R_STATUS_CLOSE;
import static com.laiketui.domain.order.OrderModel.ORDER_CLOSE;

/**
 * 功能：管理后台订单管理功能接口
 *
 * @author wangxian
 */
@Service("orderIndexService")
public class IndexServiceImpl implements IndexService {

    private final Logger logger = LoggerFactory.getLogger(IndexServiceImpl.class);

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> index(AdminOrderListVo vo, HttpServletResponse response) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            if (vo.getSelfLifting() == null) {
                vo.setSelfLifting(1);
            }
            vo.setOperator(String.valueOf(GloabConst.LktConfig.LKT_CONFIG_TYPE_PT));
            resultMap = publicOrderService.pcMchOrderIndex(vo);
            if (vo.getExportType().equals(1)) {
                exportOrderData(DataUtils.cast(resultMap.get("list")), response);
                return null;
            }
        } catch (LaiKeAPIException e) {
            throw e;
        } catch (Exception e) {
            logger.error("获取订单列表 异常：", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "index");
        }
        return resultMap;
    }

    @Override
    public Map<String, Object> kuaidishow(MainVo vo, String orderNo) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);
            resultMap = publicOrderService.getLogistics(orderNo);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("获取订单物流信息 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "kuaidishow");
        }
        return resultMap;
    }

    //导出订单列表
    private void exportOrderData(List<Map<String, Object>> list, HttpServletResponse response) throws LaiKeAPIException {
        try {
            //表头
            String[] headerList = new String[]{"订单编号", "详情id", "创单时间", "产品名称", "规格", "件数", "价格", "订单总计", "数量", "下单类型", "订单状态", "订单类型", "用户ID", "联系人"
                    , "电话", "地址", "支付方式", "物流单号", "运费"};
            //对应字段
            String[] kayList = new String[]{"orderno", "detailId", "createDate", "goodsName", "attrStr", "needNum", "goodsPrice", "orderPrice", "goodsNum", "operationTypeName","status", "otype", "userId", "userName"
                    , "mobile", "addressInfo", "payName", "courier_num", "detailFreight"};
            ExcelParamVo vo = new ExcelParamVo();
            vo.setTitle("订单列表");
            vo.setHeaderList(headerList);
            vo.setValueList(kayList);
            vo.setList(list);
            vo.setResponse(response);
            vo.setNeedNo(true);
            EasyPoiExcelUtil.excelExport(vo);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("导出订单列表数据 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "exportOrderData");
        }
    }

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public Map<String, Object> orderCount(MainVo vo) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            Map<String, Object> parmaMap = new HashMap<>(16);
            parmaMap.put("store_id", vo.getStoreId());
            parmaMap.put("status", DictionaryConst.OrdersStatus.ORDERS_R_STATUS_CONSIGNMENT);
            parmaMap.put("storeRecycle", OrderModel.SHOW);
            //统计代发货的订单数量
            Map<String, Object> parmaOrderMap = new HashMap<>(16);
            parmaOrderMap.putAll(parmaMap);
            List<String> list = new ArrayList<>();
            list.add(DictionaryConst.OrdersType.ORDERS_HEADER_GM);
//            list.add(DictionaryConst.OrdersType.ORDERS_HEADER_FX);
            parmaOrderMap.put("orderTypeList", list);
            parmaOrderMap.put("self_lifting", DictionaryConst.WhetherMaven.WHETHER_NO);
            int orderNum = orderModelMapper.countAdminOrderList(parmaOrderMap);
            //统计待发货 实物 订单
            Map<String, Object> parmaMap1 = new HashMap<>(16);
            parmaMap1.putAll(parmaMap);
            parmaMap1.put("orderType", DictionaryConst.OrdersType.ORDERS_HEADER_GM);
            parmaMap1.put("self_lifting", DictionaryConst.WhetherMaven.WHETHER_NO);
            int shiWuNum = orderModelMapper.countAdminOrderList(parmaMap1);
            //统计 活动 订单
            Map<String, Object> parmaMap2 = new HashMap<>(16);
            parmaMap2.putAll(parmaMap);
            list = new ArrayList<>();
            list.add(DictionaryConst.OrdersType.ORDERS_HEADER_GM);
            list.add(DictionaryConst.OrdersType.ORDERS_HEADER_VI);
            parmaMap2.put("self_lifting", DictionaryConst.WhetherMaven.WHETHER_NO);
            parmaMap2.put("orderTypeList_not", list);
            int activityNum = orderModelMapper.countAdminOrderList(parmaMap2);

            //统计 退货列表 订单
            int returnNum = returnOrderModelMapper.countOrderReturnWaitByStoreStatus(vo.getStoreId(), DictionaryConst.ReturnOrderStatus.RETURNORDERSTATUS_EXAMEWAIT_STATUS, DictionaryConst.OrdersType.ORDERS_HEADER_GM);

            resultMap.put("orderNum", orderNum);
            resultMap.put("shiWuNum", shiWuNum);
            resultMap.put("activityNum", activityNum);
            resultMap.put("returnNum", returnNum);
        } catch (LaiKeAPIException e) {
            throw e;
        } catch (Exception e) {
            logger.error("订单统计 异常：", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "orderCount");
        }
        return resultMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> close(AdminOrderVo orderVo) throws LaiKeAPIException {
        Map returnMap = Maps.newHashMap();
        try {
            AdminModel adminModel = RedisDataTool.getRedisAdminUserCache(orderVo.getAccessId(), redisUtil);
            int storeId = orderVo.getStoreId();
            String sNo = orderVo.getOid();
            OrderDetailsModel orderDetailsModel = new OrderDetailsModel();
            orderDetailsModel.setR_status(ORDERS_R_STATUS_CLOSE);
            Map params = Maps.newHashMap();
            params.put("status", ORDER_CLOSE);
            params.put("storeId", storeId);
            params.put("orderno", sNo);
            int row = orderModelMapper.updateOrderInfo(params);
            if (row < 1) {
                logger.info(sNo + "修改订单状态失败:");
            }
            int row1 = orderDetailsModelMapper.updateOrderDetailsStatus(storeId, sNo, ORDER_CLOSE);
            logger.info(sNo + "订单关闭:");
            if (row1 < 1) {
                logger.info("sNo 修改订单状态失败！");
            }
            orderDetailsModel.setStore_id(storeId);
            orderDetailsModel.setR_sNo(sNo);
            List<OrderDetailsModel> orderDetailsModels = orderDetailsModelMapper.select(orderDetailsModel);
            for (OrderDetailsModel orderDetailsInfo : orderDetailsModels) {
                int pid = orderDetailsInfo.getP_id();
                int goodsNum = orderDetailsInfo.getNum();
                String attributeId = orderDetailsInfo.getSid();
                ConfiGureModel confiGureModel = new ConfiGureModel();
                confiGureModel.setId(Integer.valueOf(attributeId));
                confiGureModel.setPid(pid);
                confiGureModel = confiGureModelMapper.selectOne(confiGureModel);
                int totalNum = confiGureModel.getNum();
                row = productListModelMapper.addGoodsStockNum(pid, goodsNum);
                if (row < 1) {
                    logger.info("修改商品库存失败！");
                }
                confiGureModel.setNum(goodsNum);
                confiGureModel.setTotal_num(0);
                row = confiGureModelMapper.addGoodsAttrStockNum(confiGureModel);
                if (row < 1) {
                    logger.info("修改商品属性库存失败！");
                }
                String content = " 管理员关闭订单【" + orderDetailsInfo.getR_sNo() + "】，返还库存" + goodsNum;
                StockModel stockModel = new StockModel();
                stockModel.setStore_id(storeId);
                stockModel.setProduct_id(pid);
                stockModel.setAttribute_id(Integer.valueOf(attributeId));
                stockModel.setTotal_num(totalNum);
                stockModel.setFlowing_num(goodsNum);
                stockModel.setType(0);
                stockModel.setUser_id(orderDetailsInfo.getUser_id());
                stockModel.setAdd_date(new Date());
                stockModel.setContent(content);
                stockModelMapper.insert(stockModel);

                //记录日志
                publiceService.addAdminRecord(orderVo.getStoreId(), adminModel.getName(), "关闭订单:" + sNo, AdminRecordModel.Type.DEL_ORDER, AdminRecordModel.Source.PC_PLATFORM);
            }
            returnMap.put("code", 200);
            return returnMap;
        } catch (LaiKeAPIException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("关闭订单失败：{}", e.getMessage());
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "close");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> del(MainVo vo, String orders) throws LaiKeAPIException {
        Map<String, Object> returnMap = Maps.newHashMap();
        try {
            AdminModel adminModel = RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);

            String adminName = adminModel.getName();
            int storeId = vo.getStoreId();
            String[] orderList = orders.split(SplitUtils.DH);
            for (String orderNo : orderList) {
                //商城删除订单
                int row1 = orderDetailsModelMapper.storeDelOrderDetails(storeId, orderNo);
                int row2 = orderModelMapper.storeDelOrder(storeId, orderNo);
                if (row1 >= 0 && row2 >= 0){
                    //判断用户、商家、平台是否都已经删除订单
                    publicOrderService.allDelOrder(storeId, orderNo);
                }else {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_SCSB, "删除失败", "delOrder");
                }
                OrderModel orderModel = new OrderModel();
                orderModel.setStore_id(storeId);
                orderModel.setsNo(orderNo);
                orderModel = orderModelMapper.selectOne(orderModel);
                publiceService.addAdminRecord(vo.getStoreId(),"删除了订单ID：" + orderModel.getsNo() + "的信息", AdminRecordModel.Type.DEL_ORDER, vo.getAccessId());
            }
            return returnMap;
        } catch (LaiKeAPIException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("删除订单失败：{}", e.getMessage());
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "del");
        }
    }

    @Override
    public List<Map<String, Object>> orderPrint(AdminOrderVo orderVo) throws LaiKeAPIException {
        Map returnMap = Maps.newHashMap();
        try {
            AdminModel adminModel = RedisDataTool.getRedisAdminUserCache(orderVo.getAccessId(), redisUtil);
            //获取管理后台订单打印配置
            PrintSetupModel printSetupModel = new PrintSetupModel();
            printSetupModel.setStoreId(orderVo.getStoreId());
            printSetupModel.setMchId(0);
            printSetupModel = printSetupModelMapper.selectOne(printSetupModel);
            HashMap<String, Object> printSetupMap = new HashMap<>();
            if (printSetupModel != null){
                printSetupMap.put("printName", printSetupModel.getPrintName());
                printSetupMap.put("printUrl", printSetupModel.getPrintUrl());
                printSetupMap.put("printSheng", printSetupModel.getSheng());
                printSetupMap.put("printShi", printSetupModel.getShi());
                printSetupMap.put("printxian", printSetupModel.getXian());
                printSetupMap.put("printAddress", printSetupModel.getAddress());
                printSetupMap.put("printPhone", printSetupModel.getPhone());
            }
            //订单号
            String sNos = orderVo.getsNo();
            String[] orderNos = sNos.split(SplitUtils.DH);
            List<Map<String, Object>> orderDetailsInfo = new ArrayList<>();
            for (String sNo : orderNos) {
                AdminOrderDetailVo adminOrderDetailVo = new AdminOrderDetailVo();
                adminOrderDetailVo.setStoreId(orderVo.getStoreId());
                adminOrderDetailVo.setId(sNo);
                adminOrderDetailVo.setOperationName(adminModel.getName());
                Map<String, Object> tmpOrderDetails = publicOrderService.orderPcDetails(adminOrderDetailVo);
                tmpOrderDetails.putAll(printSetupMap);
                Map tmpMap = Maps.newHashMap();
                tmpMap.put("list", tmpOrderDetails);
                orderDetailsInfo.add(tmpMap);
            }
            return orderDetailsInfo;
        } catch (LaiKeAPIException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("打印订单失败", e.getMessage());
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "orderPrint");
        }
    }

    /**
     * 获取快递公司信息
     *
     * @param express
     * @return
     * @throws LaiKeAPIException
     */
    @Override
    public Map<String, Object> searchExpress(String express) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            Map<String, Object> paramMap = new HashMap<>(16);
            paramMap.put("is_open", 1);
            paramMap.put("sort_sort", DataUtils.Sort.DESC.toString());
            if (StringUtils.isNotEmpty(express)) {
                paramMap.put("kuaidi_name", express);
            }

            int total = expressModelMapper.countDynamic(paramMap);
            List<Map<String, Object>> expressModelList = new ArrayList<>();
            if (total > 0) {
                expressModelList = expressModelMapper.selectDynamic(paramMap);
            }
            resultMap.put("total", total);
            resultMap.put("list", expressModelList);
            return resultMap;
        } catch (LaiKeAPIException e) {
            throw e;
        } catch (Exception e) {
            logger.error("获取快递信息失败：", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "searchExpress");
        }
    }

    @Override
    public Map<String, Object> deliveryView(AdminDeliveryVo adminDeliveryVo) throws LaiKeAPIException {
        Map<String, Object> retMap = Maps.newHashMap();
        try {
            int storeId = adminDeliveryVo.getStoreId();
            if (StringUtils.isNotEmpty(adminDeliveryVo.getsNo())){
                String sNo = adminDeliveryVo.getsNo();
                List<Map<String, Object>> ordersList = orderModelMapper.getDeleiveryOrders(storeId, sNo);
                // todo 未知变量
                int put = 1;
                String mchId = "";
                List<Map<String, Object>> returnGoodsList = new ArrayList<>();
                for (Map<String, Object> orderInfo : ordersList) {
                    mchId = com.laiketui.common.utils.tool.str.StringUtils.trim(MapUtils.getString(orderInfo, "mch_id"), SplitUtils.DH);
                    orderInfo.put("imgurl", publicService.getImgPath(MapUtils.getString(orderInfo, "imgurl"), storeId));
                    int rstatus = MapUtils.getIntValue(orderInfo, "r_status");
                    if (rstatus == 1) {
                        put = 0;
                    }
                    orderInfo.put("deliverNum", MapUtils.getIntValue(orderInfo, "num") - MapUtils.getIntValue(orderInfo, "deliver_num"));
                    returnGoodsList.add(orderInfo);
                }
                retMap.put("id", sNo);
                retMap.put("put", put);
                retMap.put("goods", returnGoodsList);
                retMap.put("count", returnGoodsList.size());
                retMap.put("logistics_type", publicExpressService.getMchHaveExpressSubtableByMchId(adminDeliveryVo, Integer.valueOf(mchId)));
            }
            retMap.put("express", searchExpress(null));
            return retMap;
        } catch (LaiKeAPIException e) {
            throw e;
        } catch (Exception e) {
            logger.error("获取发货信息失败", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "deliveryView");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deliverySave(MainVo vo, Integer exId, String exNo, String orderDetailIds) throws LaiKeAPIException {
        try {
            // 请选择快递公司
            if (exId == null) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_QXZKDGS, "请选择快递公司");
            }
            if (com.laiketui.core.diyJavaFunction.StringUtils.isEmpty(exNo)) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_QSRKDDH, "请输入快递单号");
            }
            int count = orderDetailsModelMapper.getDeliverNumByExIdAndExNo(exId.toString(), exNo);
            if (count > 0) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_KDDHYCZ, "快递单号已存在");
            }

            publicOrderService.adminDelivery(vo, exId, exNo, orderDetailIds);
        } catch (LaiKeAPIException e) {
            throw e;
        } catch (Exception e) {
            logger.error("订单发货 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "orderPrint");
        }

    }

    @Override
    public Map<String, Object> editOrderView(OrderModifyVo orderVo) throws LaiKeAPIException {
        Map<String, Object> retMap = Maps.newConcurrentMap();
        try {
            // 订单id sno
            String sNo = orderVo.getsNo();
            AdminOrderDetailVo adminOrderDetailVo = new AdminOrderDetailVo();
            adminOrderDetailVo.setId(sNo);
            adminOrderDetailVo.setsNo(sNo);
            adminOrderDetailVo.setOrderType("modify");
            adminOrderDetailVo.setType(orderVo.getType());
            adminOrderDetailVo.setStoreId(orderVo.getStoreId());
            Map<String, Object> adminOrderDetailsMap = publicOrderService.orderPcDetails(adminOrderDetailVo);
            List<ExpressModel> expressModels = publicExpressServicer.getExpressInfo();
            adminOrderDetailsMap.put("express", expressModels);
            retMap.putAll(adminOrderDetailsMap);
        } catch (LaiKeAPIException e) {
            throw e;
        } catch (Exception e) {
            logger.error("订单编辑失败", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDXQHQSB, "订单详情获取失败", "editOrderView");
        }
        return retMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveEditOrder(EditOrderVo orderVo) throws LaiKeAPIException {
        try {
            AdminModel userCache = RedisDataTool.getRedisAdminUserCache(orderVo.getAccessId(), redisUtil);
            if (StringUtils.isEmpty(orderVo.getOrderNo())) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDBJSB, "订单编辑失败");
            }
            publicOrderService.modifyOrder(orderVo);

            OrderModel orderModel = new OrderModel();
            orderModel.setStore_id(orderVo.getStoreId());
            orderModel.setsNo(orderVo.getOrderNo());
            orderModel = orderModelMapper.selectOne(orderModel);
            publiceService.addAdminRecord(orderVo.getStoreId(),"修改了订单ID：" + orderModel.getsNo() + "的信息", AdminRecordModel.Type.UPDATE, orderVo.getAccessId());
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("订单编辑失败", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDBJSB, "订单编辑失败", "saveEditOrder");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> helpOrder(HelpOrderVo vo) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            AdminModel adminModel = RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);
            int row;
            //商品信息
            List<Map<String, Object>> goodsList;
            try {
                goodsList = JSON.parseObject(URLDecoder.decode(vo.getProducts(), GloabConst.Chartset.UTF_8), new TypeReference<List<Map<String, Object>>>() {
                });
            } catch (Exception e) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_SPCSCW, "商品参数错误");
            }
            if (com.laiketui.common.utils.tool.str.StringUtils.isEmpty(vo.getAddressId())){
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_CSCW, "参数错误,用户收货地址id为null");
            }
            //获取会员信息
            User user = new User();
            user.setStore_id(vo.getStoreId());
            user.setUser_id(vo.getUserId());
            user = userBaseMapper.selectOne(user);
            if (user == null) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HYBCZ, "会员不存在");
            }
            //获取会员收货地址
            UserAddress userAddress = publicAddressService.findAddress(vo.getStoreId(), user.getUser_id(), vo.getAddressId());
            if (userAddress == null) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_QXZSHDZ, "请选择收货地址");
            }
            if (StringUtils.isEmpty(vo.getWipeOff())) {
                vo.setWipeOff("0");
            }

            OrderModel orderSave = new OrderModel();
            orderSave.setStore_id(vo.getStoreId());
            //生成订单号
            String orderNo = publicOrderService.createOrderNo(DictionaryConst.OrdersType.ORDERS_HEADER_GM);
            orderSave.setsNo(orderNo);
            //生产支付订单号
            String sealNo = publicOrderService.createOrderNo(DictionaryConst.OrdersType.ORDERS_HEADER_GM);
            orderSave.setReal_sno(sealNo);
            //优惠金额
            BigDecimal wipeOff = new BigDecimal(vo.getWipeOff());
            //订单总价
            BigDecimal orderPriceTotal = BigDecimal.ZERO;
            //订单商品总价
            BigDecimal orderGoodsPrice = BigDecimal.ZERO;
            //商品所属店铺
            Set<Integer> goodsMchIds = new HashSet<>();
            //总运费
            BigDecimal zfreight = BigDecimal.ZERO;
            //订单商品个数
            int orderNeedNum = 0;
            //每个商品价格,用于计算平摊
            Map<Integer, BigDecimal> currentPriceMap = new HashMap<>(16);
            //每个商品所有规格运费和
            Map<Integer, BigDecimal> goodsYunFeiMap = new HashMap<>(16);
            for (Map<String, Object> goods : goodsList) {
                int needNum = MapUtils.getIntValue(goods, "num");
                int attrId = MapUtils.getIntValue(goods, "id");
                int goodsId = MapUtils.getIntValue(goods, "pid");
                BigDecimal freight = new BigDecimal(MapUtils.getString(goods, "freight"));
                ConfiGureModel confiGureModel = confiGureModelMapper.selectByPrimaryKey(attrId);
                BigDecimal goodsAmt = confiGureModel.getPrice().multiply(new BigDecimal(needNum));
                currentPriceMap.put(confiGureModel.getId(), goodsAmt);
                orderGoodsPrice = orderGoodsPrice.add(goodsAmt);
                zfreight = zfreight.add(freight);
                if (goodsYunFeiMap.containsKey(goodsId)){
                    goodsYunFeiMap.put(goodsId, goodsYunFeiMap.get(goodsId).add(freight));
                }else {
                    goodsYunFeiMap.put(goodsId, freight);
                }
            }
            //获取商品信息
            for (Map<String, Object> goods : goodsList) {
                int needNum = MapUtils.getIntValue(goods, "num");
                int attrId = MapUtils.getIntValue(goods, "id");
                int goodsId = MapUtils.getIntValue(goods, "pid");
                String goodsName;
                BigDecimal goodsAttrPrice;
                //手动优惠金额
                BigDecimal manualOffer = BigDecimal.ZERO;

                Map<String, Object> parmaMap = new HashMap<>(16);
                parmaMap.put("store_id", vo.getStoreId());
                parmaMap.put("goodsId", goodsId);
                parmaMap.put("attr_id", attrId);
                List<Map<String, Object>> configureList = confiGureModelMapper.getProductListLeftJoinMchDynamic(parmaMap);
                if (configureList == null || configureList.size() < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_SPCSCW, "商品参数错误");
                }
                Map<String, Object> configureMap = configureList.get(0);
                goodsName = MapUtils.getString(configureMap, "product_title");
                //商品单价
                goodsAttrPrice = new BigDecimal(MapUtils.getString(configureMap, "price"));
                //商品总价
                BigDecimal goodsAmt = goodsAttrPrice.multiply(new BigDecimal(needNum));
                //为店铺添加一条购买记录
                MchBrowseModel mchBrowseSave = new MchBrowseModel();
                mchBrowseSave.setStore_id(vo.getStoreId());
                mchBrowseSave.setMch_id(MapUtils.getString(configureMap, "mch_id"));
                mchBrowseSave.setUser_id(user.getUser_id());
                mchBrowseSave.setEvent("购买了商品");
                mchBrowseSave.setAdd_time(new Date());
                mchBrowseModelMapper.insertSelective(mchBrowseSave);
                if (StringUtils.isNotEmpty(mchBrowseSave.getMch_id())) {
                    goodsMchIds.add(Integer.valueOf(mchBrowseSave.getMch_id()));
                }
                //计算单个商品价格
                if (BigDecimal.ZERO.compareTo(wipeOff) < 0) {
                    //有优惠的情况下均摊优惠
                    manualOffer = DataAlgorithmTool.orderPriceAverage(orderGoodsPrice, currentPriceMap, wipeOff).get(attrId);
                }
                List<Map<String, Object>> list = new ArrayList<>();
                parmaMap = new HashMap<>();
                parmaMap.put("num", needNum);
                list.add(parmaMap);
                parmaMap = new HashMap<>();
                parmaMap.put("pid", goodsId);
                list.add(parmaMap);
                parmaMap = new HashMap<>();
                parmaMap.put("cid", attrId);
                list.add(parmaMap);
                //获取商品运费信息
                List<Map<String, Object>> productsListMap = publiceService.productsList(list, null, 0, DictionaryConst.OrdersType.ORDERS_HEADER_GM);
                if (CollectionUtils.isEmpty(productsListMap)) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_KCBZ, "库存不足2", "settlement");
                }
                BigDecimal goodsYunFei = goodsYunFeiMap.get(goodsId);
                //记录订单明细
                OrderDetailsModel orderDetailsModel = new OrderDetailsModel();
                orderDetailsModel.setStore_id(vo.getStoreId());
                orderDetailsModel.setUser_id(user.getUser_id());
                orderDetailsModel.setP_id(goodsId);
                orderDetailsModel.setP_name(goodsName);
                orderDetailsModel.setP_price(goodsAttrPrice);
                orderDetailsModel.setNum(needNum);
                orderDetailsModel.setFreight(goodsYunFei);
                orderDetailsModel.setUnit(MapUtils.getString(configureMap, "unit"));
                orderDetailsModel.setR_sNo(orderNo);
                orderDetailsModel.setAdd_time(new Date());
                orderDetailsModel.setR_status(DictionaryConst.OrdersStatus.ORDERS_R_STATUS_CONSIGNMENT);
                orderDetailsModel.setSize(GoodsDataUtils.getProductSku(MapUtils.getString(configureMap, "attribute")));
                orderDetailsModel.setSid(attrId + "");
                orderDetailsModel.setManual_offer(manualOffer);
                orderDetailsModel.setAfter_discount(goodsAmt.subtract(manualOffer));
                if (BigDecimal.ZERO.compareTo(orderDetailsModel.getAfter_discount()) > 0) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_YHJESRYW, "立减金额输入有误");
                }
                row = orderDetailsModelMapper.insertSelective(orderDetailsModel);
                if (row < 1) {
                    logger.debug("添加订单详情失败 代客下单失败");
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_XDSB, "下单失败");
                }
                //统计订单总金额
                orderPriceTotal = orderPriceTotal.add(orderDetailsModel.getAfter_discount());
                //库存记录
                AddStockVo addStockVo = new AddStockVo();
                addStockVo.setId(attrId);
                addStockVo.setPid(goodsId);
                addStockVo.setAddNum(-needNum);
                addStockVo.setStoreId(vo.getStoreId());
                addStockVo.setText(String.format("待客(%s)下单,商品出库:%s", user.getUser_id(), needNum));
                publicStockService.addGoodsStock(addStockVo, adminModel.getName());
                //增加销量
                productListModelMapper.updateProductListVolume(needNum, vo.getStoreId(), goodsId);
            }
            //总运费为0， 更新子订单运费为0
            if (zfreight.compareTo(BigDecimal.ZERO) <= 0){
                row = orderDetailsModelMapper.updateFreightZEROByRsNo(orderNo);
                if (row < 1) {
                    logger.debug("总运费为0， 更新子订单运费为0失败 代客下单失败");
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_XDSB, "下单失败");
                }
            }
            //订单金额加总运费
            orderPriceTotal = orderPriceTotal.add(zfreight);
            //记录订单主信息
            orderSave.setUser_id(user.getUser_id());
            orderSave.setName(userAddress.getName());
            orderSave.setMobile(userAddress.getTel());
            orderSave.setNum(orderNeedNum);
            orderSave.setZ_freight(zfreight);
            orderSave.setOld_freight(zfreight);
            orderSave.setManual_offer(new BigDecimal(vo.getWipeOff()));
            orderSave.setZ_price(orderPriceTotal);
            orderSave.setOld_total(orderPriceTotal);
            orderSave.setSheng(userAddress.getSheng());
            orderSave.setShi(userAddress.getCity());
            orderSave.setXian(userAddress.getQuyu());
            orderSave.setAddress(userAddress.getAddress());
            orderSave.setRemark("");
            orderSave.setCoupon_price(wipeOff);
            orderSave.setPreferential_amount(wipeOff);
            orderSave.setManual_offer(wipeOff);
            orderSave.setPay(DictionaryConst.OrderPayType.ORDERPAYTYPE_WALLET_PAY);
            orderSave.setAdd_time(new Date());
            orderSave.setStatus(DictionaryConst.OrdersStatus.ORDERS_R_STATUS_CONSIGNMENT);
            orderSave.setSpz_price(orderGoodsPrice);
            orderSave.setSource(Integer.valueOf(DictionaryConst.StoreSource.LKT_LY_006));
            orderSave.setOtype(DictionaryConst.OrdersType.ORDERS_HEADER_GM);
            orderSave.setMch_id(com.laiketui.common.utils.tool.str.StringUtils.stringImplode(new ArrayList<>(goodsMchIds), SplitUtils.DH, true));
            orderSave.setRemarks("");
            orderSave.setGrade_rate(BigDecimal.ZERO);
            orderSave.setOperation_type(3);
            orderSave.setPay_time(new Date());
            row = orderModelMapper.insertSelective(orderSave);
            if (row < 1) {
                logger.debug("添加订单失败 代客下单失败");
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_XDSB, "下单失败");
            }
            //添加操作日志
            publiceService.addAdminRecord(vo.getStoreId(), "将用户ID："+user.getUser_id()+"进行了代客下单",AdminRecordModel.Type.UPDATE, vo.getAccessId());
            //支付
            if (orderSave.getZ_price().compareTo(BigDecimal.ZERO) > 0 && vo.getIsOfflinePayment() == 1){
                publicUserService.userRechargeMoney(vo.getStoreId(), user.getId(), orderSave.getZ_price().negate(), 4, orderNo, "");
            }
            resultMap.put("sNo", orderNo);
            resultMap.put("order_id", orderSave.getId());
            resultMap.put("total", orderSave.getZ_price());
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("代客下单 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "helpOrder");
        }
        return resultMap;
    }

    @Override
    public Map<String, Object> valetOrderSettlement(HelpOrderVo vo) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);
            //商品信息
            List<Map<String, Object>> goodsList;
            try {
                goodsList = JSON.parseObject(URLDecoder.decode(vo.getProducts(), GloabConst.Chartset.UTF_8), new TypeReference<List<Map<String, Object>>>() {
                });
            } catch (Exception e) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_SPCSCW, "商品参数错误");
            }
            //获取会员信息
            User user = new User();
            user.setStore_id(vo.getStoreId());
            user.setUser_id(vo.getUserId());
            user = userBaseMapper.selectOne(user);
            if (user == null) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HYBCZ, "会员不存在");
            }
            //用户收货地址
            UserAddress userAddress = null;
            if (vo.getAddressId() != null){
                userAddress = commonAddressService.findAddress(vo.getStoreId(), vo.getUserId(), vo.getAddressId());
            }
            //全部选择商品信息
            List<Map<String, Object>> productList = new ArrayList<>();
            //订单商品总价
            BigDecimal orderGoodsPrice = BigDecimal.ZERO;
            //订单商品总价运费
            BigDecimal zfreight = BigDecimal.ZERO;
            //所有商品数量
            Integer allNum = 0;
            //获取商品信息
            for (Map<String, Object> goods : goodsList) {
                int needNum = MapUtils.getIntValue(goods, "num");
                int attrId = MapUtils.getIntValue(goods, "id");
                int goodsId = MapUtils.getIntValue(goods, "pid");
                BigDecimal freight = new BigDecimal(MapUtils.getString(goods, "freight"));
                allNum += needNum;
                //获取商品规格信息
                Map<String, Object> parmaMap = new HashMap<>(16);
                parmaMap.put("store_id", vo.getStoreId());
                parmaMap.put("goodsId", goodsId);
                parmaMap.put("attr_id", attrId);
                List<Map<String, Object>> configureList = confiGureModelMapper.getProductListLeftJoinMchDynamic(parmaMap);
                if (configureList == null || configureList.size() < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_SPCSCW, "商品参数错误");
                }
                Map<String, Object> configureMap = configureList.get(0);
                //商品单价
                BigDecimal goodsAttrPrice = new BigDecimal(MapUtils.getString(configureMap, "price"));
                //商品总价
                BigDecimal goodsAmt = goodsAttrPrice.multiply(new BigDecimal(needNum));
                orderGoodsPrice = orderGoodsPrice.add(goodsAmt);
                //商品运费
                BigDecimal goodsYunFei = freight;
                //运费为-1须计算商品运费
                if (userAddress != null && freight.equals(new BigDecimal("-1"))){
                    List<Map<String, Object>> list = new ArrayList<>();
                    parmaMap = new HashMap<>();
                    parmaMap.put("store_id", vo.getStoreId());
                    parmaMap.put("num", needNum);
                    list.add(parmaMap);
                    parmaMap = new HashMap<>();
                    parmaMap.put("pid", goodsId);
                    list.add(parmaMap);
                    parmaMap = new HashMap<>();
                    parmaMap.put("cid", attrId);
                    list.add(parmaMap);
                    //获取商品运费信息
                    List<Map<String, Object>> productsListMap = publiceService.productsList(list, null, 0, DictionaryConst.OrdersType.ORDERS_HEADER_GM);
                    if (CollectionUtils.isEmpty(productsListMap)) {
                        throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_KCBZ, "库存不足2", "settlement");
                    }
                    //按照店铺归类的商品、运费、商品总价等信息
                    Map<String, Object> productsInfo = publiceService.settlementProductsInfo(productsListMap, vo.getStoreId(), DictionaryConst.OrdersType.ORDERS_HEADER_GM);
                    //运费信息
                    Map<String, List<Map<String, Object>>> productsFreight = (Map<String, List<Map<String, Object>>>) productsInfo.get("products_freight");
                    //计算会员的产品价格和订单产品总价
                    List<Map<String, Object>> products = (List<Map<String, Object>>) productsInfo.get("products");
                    //计算会员优惠价格
                    MemberPriceVo memberPriceVo = new MemberPriceVo();
                    memberPriceVo.setUserId(vo.getUserId());
                    memberPriceVo.setStoreId(vo.getStoreId());
                    memberPriceVo.setMchProductList(products);
                    //不计算会员优惠
                    Map<String, Object> memberProductsInfo = publiceService.getMemberPrice(memberPriceVo, 0);
                    //拿出商品信息
                    productsListMap = (List<Map<String, Object>>) memberProductsInfo.get("products");
                    productsInfo = publicOrderService.getFreight(productsFreight, productsListMap, userAddress, vo.getStoreId(), DictionaryConst.OrdersType.ORDERS_HEADER_GM);
                    //商品运费
                    goodsYunFei = new BigDecimal(MapUtils.getString(productsInfo, "yunfei"));

                }
                parmaMap = new HashMap<>();
                parmaMap.put("goodsId", goodsId);
                parmaMap.put("attr_id", attrId);
                parmaMap.put("store_id", vo.getStoreId());
                //查询当前商品信息
                List<Map<String, Object>> list = confiGureModelMapper.getProductListLeftJoinMchDynamic(parmaMap);
                Map<String, Object> product = list.get(0);
                product.put("imgurl", publiceService.getImgPath(MapUtils.getString(product, "imgurl"), vo.getStoreId()));
                product.put("attribute", GoodsDataUtils.getProductSkuValue(MapUtils.getString(product, "attribute")));
                if (goodsYunFei.compareTo(BigDecimal.ZERO) < 0){
                    goodsYunFei = BigDecimal.ZERO;
                }
                product.put("freight", goodsYunFei);
                product.put("nums", needNum);
                zfreight = zfreight.add(goodsYunFei);
                productList.add(product);
            }
            //平台包邮设置
            OrderConfigModal orderConfigModal = new OrderConfigModal();
            orderConfigModal.setStore_id(vo.getStoreId());
            orderConfigModal = orderConfigModalMapper.selectOne(orderConfigModal);
            //店铺包邮设置
            Integer mchId = customerModelMapper.getStoreMchId(vo.getStoreId());
            MchConfigModel mchConfigModel = new MchConfigModel();
            mchConfigModel.setStore_id(vo.getStoreId());
            mchConfigModel.setMch_id(mchId);
            mchConfigModel = mchConfigModelMapper.selectOne(mchConfigModel);
            if (orderConfigModal != null && orderConfigModal.getPackage_settings().equals(DictionaryConst.WhetherMaven.WHETHER_OK ) && zfreight.compareTo(BigDecimal.ZERO) >= 0){
                // 同单
                int sameOrder = orderConfigModal.getSame_order();
                if (sameOrder <= allNum){
                    zfreight = BigDecimal.ZERO;
                    for (Map<String, Object> product : productList) {
                        product.put("freight", BigDecimal.ZERO);
                    }
                }
            }
            if (mchConfigModel != null && mchConfigModel.getPackage_settings().equals(DictionaryConst.WhetherMaven.WHETHER_OK) && zfreight.compareTo(BigDecimal.ZERO) >= 0){
                // 同单
                int sameOrder = mchConfigModel.getSame_order();
                if (sameOrder <= allNum){
                    zfreight = BigDecimal.ZERO;
                    for (Map<String, Object> product : productList) {
                        product.put("freight", BigDecimal.ZERO);
                    }
                }
            }
            //计算订单金额
            BigDecimal orderPrice = orderGoodsPrice.subtract(new BigDecimal(vo.getWipeOff())).add(zfreight);
            if (BigDecimal.ZERO.compareTo(orderPrice) > 0) {
                orderPrice = BigDecimal.ZERO;
            }
            //商品总价
            resultMap.put("goodsPriceTotal", orderGoodsPrice);
            //支付金额
            resultMap.put("payPrice", orderPrice);
            //运费
            resultMap.put("zfreight", zfreight);
            //全部商品信息
            resultMap.put("goosdList", productList);
            return resultMap;
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("代客下单-结算 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_JSSB, "计算失败", "valetOrder");
        }
    }

    @Override
    public Map<String, Object> orderDetailsInfo(AdminOrderDetailVo orderVo) {
        try {
            String sNo = orderVo.getsNo();
            orderVo.setId(sNo);
            orderVo.setsNo(sNo);
            orderVo.setOrderType("see");
            return publicOrderService.orderPcDetails(orderVo);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("订单详情异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDBJSB, "订单编辑失败", "orderDetailsInfo");
        }
    }

    @Autowired
    private FileDeliveryModelMapper fileDeliveryModelMapper;


    /**
     * 批量发货
     *
     * @param vo    -
     * @param image -
     * @return boolean
     * @throws LaiKeAPIException -
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDelivery(MainVo vo, List<MultipartFile> image) throws LaiKeAPIException {
        try {
            AdminModel user = RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);
            ExcelAnalysisVo excelAnalysisVo = new ExcelAnalysisVo();
            excelAnalysisVo.setFile(image);
            List<String> titleNames = new ArrayList<>();
            titleNames.add("订单号");
            titleNames.add("订单明细id");
            titleNames.add("物流公司名称");
            titleNames.add("物流单号");
            excelAnalysisVo.setTitleName(titleNames);
            List<String> valueNames = new ArrayList<>();
            valueNames.add("orderNo");
            valueNames.add("detailId");
            valueNames.add("wuName");
            valueNames.add("wuNo");
            excelAnalysisVo.setValueKey(valueNames);
            Map<String, Object> resultMap = EasyPoiExcelUtil.analysisExcel(excelAnalysisVo);
            List<Map<String, Object>> excelDataList = DataUtils.cast(resultMap.get("list"));
            if (excelDataList != null) {
                //设置回滚点
//                Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
                String fileName = "";
                StringBuilder errorText = new StringBuilder();
                OrderDetailsModel orderDetailsModel;
                List<Map<String, Object>> detailIdList;
                HashMap<String, Object> detailMap;
                for (Map<String, Object> map : excelDataList) {
                    int x = MapUtils.getIntValue(map, "x");
                    fileName = MapUtils.getString(map, "fileName", "");
                    errorText.append(MapUtils.getString(map, "errorText"));
                    if (map.containsKey("orderNo")) {
                        //商品发货信息
                        String orderNo = MapUtils.getString(map, "orderNo");
                        //订单信息
                        OrderModel orderModel = new OrderModel();
                        orderModel.setStore_id(vo.getStoreId());
                        orderModel.setsNo(orderNo);
                        orderModel = orderModelMapper.selectOne(orderModel);

                        //发货
                        try {
                            //详情id
                            String detailId = MapUtils.getString(map, "detailId");
                            orderDetailsModel = orderDetailsModelMapper.selectByPrimaryKey(detailId);
                            if (orderDetailsModel == null){
                                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDBCZ,"订单不存在");
                            }
                            detailIdList = new ArrayList<>();
                            detailMap = new HashMap<>();
                            detailMap.put("detailId", orderDetailsModel.getId());
                            int DeliverNum = 0;
                            if (orderDetailsModel.getDeliverNum() != null){
                                DeliverNum = orderDetailsModel.getDeliverNum();
                            }
                            detailMap.put("num", orderDetailsModel.getNum() - DeliverNum);
                            detailIdList.add(detailMap);
                            String wuName = MapUtils.getString(map, "wuName");
                            Integer wuId = 0;
                            String wuNo = MapUtils.getString(map, "wuNo");
                            if(orderDetailsModel.getR_status().equals(DictionaryConst.OrdersStatus.ORDERS_R_STATUS_DISPATCHED)){
                                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDYFHBNJXXG,"订单已发货,不能修改");
                            }
                            if (orderModel == null){
                                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDBCZ,"订单不存在");
                            }
                            if (orderModel.getStatus() == DictionaryConst.OrdersStatus.ORDERS_R_STATUS_UNPAID){
                                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDYFHBNJXXG,"订单未付款,不能修改");
                            }
                            if (orderModel.getStatus() == DictionaryConst.OrdersStatus.ORDERS_R_STATUS_DISPATCHED){
                                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDYFHBNJXXG,"订单已发货,不能修改");
                            }
                            String mchId = StringUtils.strip(orderModel.getMch_id(), SplitUtils.DH);
                            ExpressModel expressModel = new ExpressModel();
                            expressModel.setKuaidi_name(wuName);
                            expressModel.setRecycle(DictionaryConst.ProductRecycle.NOT_STATUS);
                            expressModel = expressModelMapper.selectOne(expressModel);
                            if (expressModel != null) {
                                wuId = expressModel.getId();
                            }else {
                                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_QXZKDGS,"快递公司不存在");
                            }
                            //判断快递公司是否配置了电子面单 -配置了就进行电子面单发货
                            //获取店铺的对应物流电子面单配置
                            ExpressSubtableModel expressSubtableModel = new ExpressSubtableModel();
                            expressSubtableModel.setStoreId(vo.getStoreId());
                            expressSubtableModel.setMchId(Integer.parseInt(mchId));
                            expressSubtableModel.setExpressId(wuId);
                            expressSubtableModel.setRecovery(DictionaryConst.WhetherMaven.WHETHER_NO);
                            expressSubtableModel = expressSubtableModelMapper.selectOne(expressSubtableModel);
                            if (expressSubtableModel != null && !StringUtils.isEmpty(expressSubtableModel.getPartnerId())){
                                FaceSheetSend(vo, wuId, JSON.toJSONString(detailIdList));
                            }else {
                                deliverySave(vo, wuId, wuNo, JSON.toJSONString(detailIdList));
                            }
                        } catch (LaiKeAPIException l) {
                            logger.error("批量发货失败 异常", l);
                            //回滚
//                            TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
                            errorText.append(String.format("第%s行 %s", x, l.getMessage())).append(SplitUtils.DH);
                            //退出后面的订单循环
                            break;
                        }
                        publiceService.addAdminRecord(vo.getStoreId(), user.getName(), "将订单ID：" + orderModel.getsNo() + "进行了发货", AdminRecordModel.Type.UPDATE, AdminRecordModel.Source.PC_PLATFORM);
                    }
                }

                //记录
                FileDeliveryModel fileDeliveryModel = new FileDeliveryModel();
                fileDeliveryModel.setId(BuilderIDTool.getSnowflakeId() + "");
                fileDeliveryModel.setName(fileName);
                fileDeliveryModel.setAdd_date(new Date());
                fileDeliveryModel.setType(1);
                fileDeliveryModel.setOrderNum(excelDataList.size() - 1);
                int status = 1;
                if (com.laiketui.common.utils.tool.str.StringUtils.isNotEmpty(errorText)) {
                    status = 0;
                    fileDeliveryModel.setText(errorText.toString());
                }
                fileDeliveryModel.setStatus(status);
                fileDeliveryModel.setMch_id(user.getShop_id());
                fileDeliveryModelMapper.insertSelective(fileDeliveryModel);
                return status == 1;
            }
            return false;
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("订单发货列表 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "batchDelivery");
        }
    }
    /**
     * 发货列表
     *
     * @param vo        -
     * @param fileName  -
     * @param status    -
     * @param startDate -
     * @param endDate   -
     * @param response
     * @return Map
     * @throws LaiKeAPIException-
     */
    @Override
    public Map<String, Object> deliveryList(MainVo vo, String fileName, Integer status, String startDate, String endDate, HttpServletResponse response) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            AdminModel user = RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);
            Map<String, Object> paramMap = new HashMap<>(16);
            paramMap.put("mchId", user.getShop_id());
            paramMap.put("name", fileName);
            paramMap.put("status", status);
            paramMap.put("startDate", startDate);
            paramMap.put("endDate", endDate);
            paramMap.put("add_date_sort", DataUtils.Sort.DESC.toString());
            paramMap.put("pageStart", vo.getPageNo());
            paramMap.put("pageEnd", vo.getPageSize());
            paramMap.put("type", "1");
            int total = fileDeliveryModelMapper.countDynamic(paramMap);
            List<Map<String, Object>> resultList = new ArrayList<>();
            if (total > 0) {
                resultList = fileDeliveryModelMapper.selectDynamic(paramMap);
            }
            resultList.stream().forEach( stringObjectMap -> {
                if ((int)stringObjectMap.get("status") == 0){
                    stringObjectMap.put("statusName", "发货失败");
                }else {
                    stringObjectMap.put("statusName", "发货成功");
                }
            });
            if (vo.getExportType() == 1){
                exportBulkDeliveryData(resultList, response);
                return null;
            }
            resultMap.put("total", total);
            resultMap.put("list", resultList);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("发货列表 异常 ", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "bannerList");
        }
        return resultMap;
    }
    //导出批量发货记录
    private void exportBulkDeliveryData(List<Map<String, Object>> list, HttpServletResponse response) throws LaiKeAPIException {
        try {
            //表头
            String[] headerList = new String[]{"文件ID", "文件名称", "文件状态", "批量发货时间", "失败原因"};
            //对应字段
            String[] kayList = new String[]{"id", "name", "statusName", "goodsName", "add_date", "text"};
            ExcelParamVo vo = new ExcelParamVo();
            vo.setTitle("批量发货记录表");
            vo.setHeaderList(headerList);
            vo.setValueList(kayList);
            vo.setList(list);
            vo.setResponse(response);
            vo.setNeedNo(true);
            EasyPoiExcelUtil.excelExport(vo);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("导出订单列表数据 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "exportOrderData");
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delDelivery(MainVo vo, String id) throws LaiKeAPIException {
        try {
            AdminModel user = RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);
            FileDeliveryModel fileDeliveryModel = fileDeliveryModelMapper.selectByPrimaryKey(id);
            if (fileDeliveryModel == null) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_JLBCZ, "记录不存在");
            }
            int row = fileDeliveryModelMapper.deleteByPrimaryKey(id);
            if (row < 1) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_SCSB, "删除失败");
            }
            publiceService.addAdminRecord(vo.getStoreId(), "删除了文件id："+id+" 的批量订单发货记录的信息",AdminRecordModel.Type.DEL, vo.getAccessId());
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("删除发货记录 异常 ", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "bannerList");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> verificationExtractionCode(MainVo vo, Integer orderId, String extractionCode) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            AdminModel user = RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);
            Map<String, Object> parmaMap = new HashMap<>(16);
            parmaMap.put("store_id", vo.getStoreId());
            if (orderId == null) {
                if (extractionCode.contains(SplitUtils.DH)) {
                    parmaMap.put("extraction_code1", extractionCode);
                } else {
                    parmaMap.put("extraction_code", extractionCode);
                }
            }
            parmaMap.put("id", orderId);
            parmaMap.put("supplierPro", "supplierPro");
            List<Map<String, Object>> orderInfo = orderModelMapper.getOrdersNumDynamic(parmaMap);
            if (orderId == null && (orderInfo == null || orderInfo.size() < 1)) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_YZMCW, "验证码错误");
            }
            if (orderInfo != null && orderInfo.size() > 0) {
                Map<String, Object> map = orderInfo.get(0);
                //订单号
                String orderno = map.get("sNo").toString();
                //订单状态
                int status = Integer.parseInt(map.get("status").toString());
                //订单金额
                BigDecimal orderAmt = new BigDecimal(map.get("z_price").toString());
                //积分
                BigDecimal allow = new BigDecimal("0");
                String mchId = com.laiketui.common.utils.tool.str.StringUtils.trim(MapUtils.getString(map, "mch_id"), SplitUtils.DH);
                if (map.containsKey("allow")) {
                    allow = new BigDecimal(map.get("allow").toString());
                }
                if (status == DictionaryConst.OrdersStatus.ORDERS_R_STATUS_DISPATCHED) {
                    //取货代码 E9ds5B,1601349348,1601351148
                    String keyCode = map.get("extraction_code") + "";
                    if (com.laiketui.common.utils.tool.str.StringUtils.isEmpty(keyCode)) {
                        throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_QHMBCZ, "取货码不存在");
                    }
                    String[] codeStr = keyCode.split(",");
                    //验证码
                    String code = codeStr[0];
                    //失效时间
                    String endTime = codeStr[2];
                    //系统时间
                    String sysTime = DateUtil.timeStamp();
                    if (Long.parseLong(sysTime) > Long.parseLong(endTime)) {
                        throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_YZMYSX, "验证码已失效");
                    }
                    if (!extractionCode.equals(code)) {
                        throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_YZMCW, "验证码错误");
                    }
                    //标记订单已完成
                    parmaMap.clear();
                    parmaMap.put("orderno", orderno);
                    parmaMap.put("status", DictionaryConst.OrdersStatus.ORDERS_R_STATUS_COMPLETE);
                    int count = orderModelMapper.updateByOrdernoDynamic(parmaMap);
                    if (count < 1) {
                        logger.info("订单标记已完成失败 参数:" + com.alibaba.fastjson.JSON.toJSONString(parmaMap));
                        throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常");
                    }
                    //标记明细状态
                    parmaMap.clear();
                    parmaMap.put("orderno", orderno);
                    parmaMap.put("arrive_time", new Date());
                    parmaMap.put("r_status", DictionaryConst.OrdersStatus.ORDERS_R_STATUS_COMPLETE);
                    count = orderDetailsModelMapper.updateByOrdernoDynamic(parmaMap);
                    if (count < 1) {
                        logger.info("订单标记已完成失败 参数:" + com.alibaba.fastjson.JSON.toJSONString(parmaMap));
                        throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常");
                    }
                    //卖家收入
                    publicMchService.clientConfirmReceipt(vo.getStoreId(), Integer.parseInt(mchId), orderno, orderAmt, allow);
                    //确认收货 普通商品赠送积分(只有普通订单可以自提，if判断可以不用)
                    if (DictionaryConst.OrdersType.ORDERS_HEADER_GM.equals(MapUtils.getString(map, "otype"))) {
                        //如果订单之前已经获得了一笔积分则不再获取
                        SignRecordModel signRecordCount = new SignRecordModel();
                        signRecordCount.setStore_id(vo.getStoreId());
                        signRecordCount.setUser_id(MapUtils.getString(map, "user_id"));
                        signRecordCount.setsNo(orderno);
                        if (signRecordModelMapper.selectCount(signRecordCount) == 0) {
                            publicMemberService.memberSettlement(vo.getStoreId(), MapUtils.getString(map, "user_id"),
                                    orderno, new BigDecimal(MapUtils.getString(map, "z_price", "0")), IntegralConfigModel.GiveStatus.RECEIVING);
                        } else {
                            logger.debug("订单{}已经获得过一笔【会员购物积分】积分,此次不获嘚积分.", orderno);
                        }
                    }
                    resultMap.put("sNo", orderno);
                    resultMap.put("p_price", orderAmt);

                    publiceService.addAdminRecord(vo.getStoreId(), "核销了订单ID："+orderno,AdminRecordModel.Type.UPDATE, vo.getAccessId());
                } else {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_YZMWX, "验证码无效");
                }
            } else {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDBCZ, "订单不存在");
            }
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("验证提货码 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "verificationExtractionCode");
        }
        return resultMap;
    }


    @Override
    public Map<String, Object> ShippingRecords(GetExpressDeliveryListVo vo) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            AdminModel user = RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);
            resultMap =  publicExpressService.getExpressDeliveryList(vo);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("获取订单发货列表 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "ShippingRecords");
        }
        return resultMap;
    }

    @Override
    public Map<String, Object> expressGetPro(MainVo vo, Integer id, String name) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            AdminModel user = RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);
            resultMap =  publicExpressService.getGoodsByExpressDeliveryId(vo, id, name);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("查看发货记录商品 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "expressGetPro");
        }
        return resultMap;
    }

    @Override
    public void CancelElectronicWaybill(MainVo vo, Integer id) throws LaiKeAPIException  {
        try {
            AdminModel user = RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);
            publicOrderService.cancelElectronicSheetDelivery(vo, id);
            ExpressDeliveryModel expressDeliveryModel = expressDeliveryModelMapper.selectByPrimaryKey(id);
            publiceService.addAdminRecord(vo.getStoreId(),"取消了订单ID："+expressDeliveryModel.getsNo()+" 的面单打印",AdminRecordModel.Type.DEL_ORDER, vo.getAccessId());
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("查看发货记录商品 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "expressGetPro");
        }
    }

    @Override
    public void FaceSheetSend(MainVo vo, Integer exId, String orderDetailIds) throws LaiKeAPIException {
        try {
            AdminModel user = RedisDataTool.getRedisAdminUserCache(vo.getAccessId(), redisUtil);
            publicOrderService.electronicSheetDelivery(vo, exId, orderDetailIds);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("查看发货记录商品 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "expressGetPro");
        }
    }

    @Autowired
    private UserBaseMapper userBaseMapper;

    @Autowired
    private PublicUserService publicUserService;

    @Autowired
    private PublicAddressService publicAddressService;

    @Autowired
    private PublicStockService publicStockService;

    @Autowired
    private MchBrowseModelMapper mchBrowseModelMapper;

    @Autowired
    private PublicMemberService publicMemberService;

    @Autowired
    private OrderDetailsModelMapper orderDetailsModelMapper;

    @Autowired
    private PublicAdminRecordService publicAdminRecordService;

    @Autowired
    private ConfiGureModelMapper confiGureModelMapper;

    @Autowired
    private ProductListModelMapper productListModelMapper;

    @Autowired
    private StockModelMapper stockModelMapper;

    @Autowired
    private PublicOrderService publicOrderService;

    @Autowired
    private PubliceService publicService;

    @Autowired
    private OrderModelMapper orderModelMapper;

    @Autowired
    private ReturnOrderModelMapper returnOrderModelMapper;

    @Autowired
    private ExpressModelMapper expressModelMapper;

    @Autowired
    private PublicExpressService publicExpressServicer;

    @Autowired
    private PubliceService publiceService;

    @Autowired
    private PublicAddressService commonAddressService;

    @Autowired
    private PrintSetupModelMapper printSetupModelMapper;

    @Autowired
    private OrderConfigModalMapper orderConfigModalMapper;

    @Autowired
    private CustomerModelMapper customerModelMapper;

    @Autowired
    private MchConfigModelMapper mchConfigModelMapper;

    @Autowired
    private PublicMchService publicMchService;

    @Autowired
    private SignRecordModelMapper signRecordModelMapper;

    @Autowired
    private PublicExpressService publicExpressService;

    @Autowired
    private ExpressSubtableModelMapper expressSubtableModelMapper;

    @Autowired
    private ExpressDeliveryModelMapper expressDeliveryModelMapper;
}

